package com.zy.openchat.core.model.call;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.blankj.utilcode.util.ScreenUtils;
import com.google.gson.JsonObject;
import com.ja.openchat.R;
import com.yhao.floatwindow.FloatWindow;
import com.yhao.floatwindow.IFloatWindow;
import com.yhao.floatwindow.MoveType;
import com.yhao.floatwindow.ViewStateListener;
import com.zy.openchat.App;
import com.zy.openchat.core.manager.TelegramManager;
import com.zy.openchat.core.manager.TgEvent;
import com.zy.openchat.core.manager.TgResponse;
import com.zy.openchat.core.manager.TgResultBlock;
import com.zy.openchat.core.model.user.UserInfo;
import com.ja.openchat.ui.chat.call.C2CCallActivity;
import com.zy.openchat.Constants;
import com.zy.openchat.util.LocalNotificationHelper;
import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.interfaces.OnSelectListener;

import org.apache.commons.lang3.StringUtils;
import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import io.agora.rtc.IRtcEngineEventHandler;
import io.agora.rtc.RtcEngine;
import io.agora.rtc.video.VideoCanvas;

public class CallManager {
    //通话过程状态定义
    public enum CallingState {
        CallingState_Init, //初始状态
        CallingState_None, //无状态
        CallingState_Outgoing_Prepare, //呼出准备中
        CallingState_Outgoing_Prepare_error,//呼出准备失败
        CallingState_Outgoing_Calling, //呼出中，等待对方接听
        CallingState_Incoming_Waiting, //来电等待中
        CallingState_Incoming_Prepare, //来电接听前准备中
        CallingState_Canceled, //自己取消
        CallingState_Canceled_2_Timeout, //对方无应答\自己超时
        CallingState_C2C_Canceled, //对方取消
        CallingState_In_Calling, //通话中
        CallingState_Call_End, //通话结束
    }

    private volatile static CallManager g_callManager;

    private CallManager() {
        load();
    }

    public static CallManager getCallManager() {
        if (g_callManager == null) {
            synchronized (CallManager.class) {
                if (g_callManager == null) {
                    g_callManager = new CallManager();
                }
            }
        }
        return g_callManager;
    }

    private static final String TAG = "CallManager";
    private LocalCallInfo curCallInfo;

    //声网sdk
    private RtcEngine agoraKit;

    //超时处理
    private Timer timerRefreshTask;

    //本地是否静音
    private boolean isLocalVoiceMute;
    private boolean isUserControlLocalVoiceMute;

    //传感器
    private PowerManager.WakeLock wakeLock;

    private void load() {
        try {
            agoraKit = RtcEngine.create(App.getInstanse(), Constants.getAgoraAppId(), mRtcEventHandler);
        } catch (Exception e) {
            Constants.Loge(TAG, e.getLocalizedMessage());
        }
        //添加设备（耳机）插入|拔出检测
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.intent.action.HEADSET_PLUG");
        App.getInstanse().registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Headset_State_Changed, null));
            }
        }, intentFilter);
    }

    private IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
        @Override
        public void onError(int errorCode) {
            super.onError(errorCode);
            Constants.Loge(TAG, "AgoraRtc->onError:" + errorCode);
            //主线程执行
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    //    - `-2`(`AgoraErrorCodeInvalidArgument`): The parameter is invalid.
                    //    - `-3`(`AgoraErrorCodeNotReady`): The SDK fails to be initialized. You can try re-initializing the SDK.
                    //    - `-5`(`AgoraErrorCodeRefused`): The request is rejected. This may be caused by the following:
                    if (curCallInfo.callState == CallingState.CallingState_Outgoing_Prepare) {
                        if (errorCode == ErrorCode.ERR_INVALID_ARGUMENT ||
                                errorCode == ErrorCode.ERR_NOT_READY ||
                                errorCode == ErrorCode.ERR_REFUSED) {
                            curCallInfo.callState = CallingState.CallingState_Outgoing_Prepare_error;
                            showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_video_call) : App.getInstanse().getString(R.string.failed_voice_call));
                            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                            resetCallInfoToSmallTopView();
                            destroyCall();
                        }
                    }
                    if (curCallInfo.callState == CallingState.CallingState_Incoming_Prepare) {
                        if (errorCode == ErrorCode.ERR_INVALID_ARGUMENT ||
                                errorCode == ErrorCode.ERR_NOT_READY ||
                                errorCode == ErrorCode.ERR_REFUSED) {
                            curCallInfo.callState = CallingState.CallingState_Canceled;
                            showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_answer_video) : App.getInstanse().getString(R.string.failed_answer_voice));
                            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                            resetCallInfoToSmallTopView();
                            destroyCall();
                        }
                    }
                }
            });
        }

        @Override
        public void onJoinChannelSuccess(String channel, int uid, int elapsed) {//当前用户加入频道
            super.onJoinChannelSuccess(channel, uid, elapsed);
            Constants.Logd(TAG, String.format("AgoraRtc->onJoinChannelSuccess:%s,%d,%d", channel, uid, elapsed));
            //主线程执行
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (!StringUtils.isEmpty(channel) && channel.equals(curCallInfo.channelName)) {//当前通话，已成功加入频道
                        if (curCallInfo.isMeetingAV) {//会议
                        } else {//单聊
                            if (curCallInfo.callState == CallingState.CallingState_Outgoing_Prepare) {
                                //呼叫中
                                curCallInfo.callState = CallingState.CallingState_Outgoing_Calling;
                                curCallInfo.callTime = new Date().getTime() / 1000;
                                //开启超时处理机制
                                stopRefreshTimer();
                                startRefreshTimer(500);
                                //通知页面刷新
                                EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                                resetCallInfoToSmallTopView();
                                //播放呼叫铃声
                                int code = agoraKit.getAudioEffectManager().playEffect(1, "/assets/ringtone.mp3", 0, 1.0f, 0.0f, 100.0f, false, 0);
                                Constants.Loge(TAG, "playEffect:" + code);
                            } else if (curCallInfo.callState == CallingState.CallingState_Incoming_Prepare) {
                                curCallInfo.incoming_join_time = new Date().getTime() / 1000;
                                //开启超时处理机制
                                stopRefreshTimer();
                                startRefreshTimer(500);
                            } else {//异常处理
                            }
                        }
                    } else {//异常处理
                    }
                }
            });
        }

        @Override
        public void onRejoinChannelSuccess(String channel, int uid, int elapsed) {//当前用户重新加入频道
            super.onRejoinChannelSuccess(channel, uid, elapsed);
            Constants.Logd(TAG, String.format("AgoraRtc->onRejoinChannelSuccess:%s,%d,%d", channel, uid, elapsed));
        }

        @Override
        public void onLeaveChannel(RtcStats stats) {//当前用户离开频道
            super.onLeaveChannel(stats);
            Constants.Logd(TAG, String.format("AgoraRtc->onLeaveChannel:%s", stats.toString()));
        }

        @Override
        public void onUserJoined(int uid, int elapsed) {//对方加入频道
            super.onUserJoined(uid, elapsed);
            Constants.Logd(TAG, String.format("AgoraRtc->onUserJoined:%d,%d", uid, elapsed));
            //主线程执行
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (curCallInfo.isMeetingAV) {//会议
                    } else {//单聊
                        if (isIncoming()) {//来电
                            if (curCallInfo.callState == CallingState.CallingState_Incoming_Prepare) {
                                //已加入通话
                                TelegramManager.getTelegramManager().startCall(App.getInstanse(), curCallInfo.callId, new TgResultBlock<TgResponse>() {
                                    @Override
                                    public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                                    }

                                    @Override
                                    public void onTimeout(Map<String, Object> request) {
                                    }
                                });
                                //
                                curCallInfo.callState = CallingState.CallingState_In_Calling;
                                curCallInfo.startTime = new Date().getTime() / 1000;
                                //开启通话时间刷新机制
                                stopRefreshTimer();
                                startRefreshTimer(500);
                                //通知页面刷新
                                EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                                resetCallInfoToSmallTopView();
                                //停止呼叫铃声
                                agoraKit.getAudioEffectManager().stopEffect(1);
                                LocalNotificationHelper.stopIncoming();
                                //添加近距离传感器
                                initSensor();
                                //开启本地语音或者视频
                                if (isVideo()) {//视频
                                    agoraKit.muteLocalVideoStream(false);
                                } else {//语音
                                    if (isUserControlLocalVoiceMute) {
                                        agoraKit.muteLocalAudioStream(isLocalVoiceMute);
                                    } else {
                                        isLocalVoiceMute = false;
                                        agoraKit.muteLocalAudioStream(isLocalVoiceMute);
                                    }
                                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_Local_Voice_Mute_Changed, null));
                                }
                            } else {//异常处理
                            }
                        } else {//呼出-等待对方进入则会话开始
                            //已加入通话
                            TelegramManager.getTelegramManager().startCall(App.getInstanse(), curCallInfo.callId, new TgResultBlock<TgResponse>() {
                                @Override
                                public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                                }

                                @Override
                                public void onTimeout(Map<String, Object> request) {
                                }
                            });
                            //
                            curCallInfo.callState = CallingState.CallingState_In_Calling;
                            curCallInfo.startTime = new Date().getTime() / 1000;
                            //通知页面刷新
                            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                            resetCallInfoToSmallTopView();
                            //停止呼叫铃声
                            agoraKit.getAudioEffectManager().stopEffect(1);
                            LocalNotificationHelper.stopIncoming();
                            //添加近距离传感器通知
                            initSensor();
                            //开启本地语音或者视频
                            if (isVideo()) {//视频
                                agoraKit.muteLocalVideoStream(false);
                            } else {//语音
                                if (isUserControlLocalVoiceMute) {
                                    agoraKit.muteLocalAudioStream(isLocalVoiceMute);
                                } else {
                                    isLocalVoiceMute = false;
                                    agoraKit.muteLocalAudioStream(isLocalVoiceMute);
                                }
                                EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_Local_Voice_Mute_Changed, null));
                            }
                        }
                    }
                }
            });
        }

        @Override
        public void onUserOffline(int uid, int reason) {//对方离开频道
            super.onUserOffline(uid, reason);
            Constants.Logd(TAG, String.format("AgoraRtc->onUserOffline:%d,%d", uid, reason));
            //主线程执行
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    if (curCallInfo.callState == CallingState.CallingState_In_Calling) {
                        if (curCallInfo.isMeetingAV) {//会议
                        } else {
                            curCallInfo.callState = CallingState.CallingState_C2C_Canceled;
                            showTips(App.getInstanse().getString(R.string.other_hung_up));
                            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                            resetCallInfoToSmallTopView();
                            destroyCall();
                        }
                    }
                }
            });
        }

        @Override
        public void onAudioRouteChanged(int routing) {
            super.onAudioRouteChanged(routing);
            Constants.Logd(TAG, String.format("AgoraRtc->onAudioRouteChanged:%d", routing));
            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Headset_State_Changed, null));
        }

        @Override
        public void onAudioPublishStateChanged(String channel, int oldState, int newState, int elapseSinceLastState) {
            super.onAudioPublishStateChanged(channel, oldState, newState, elapseSinceLastState);
        }

        @Override
        public void onFirstLocalVideoFrame(int width, int height, int elapsed) {
            super.onFirstLocalVideoFrame(width, height, elapsed);
        }

        @Override
        public void onFirstRemoteVideoFrame(int uid, int width, int height, int elapsed) {
            super.onFirstRemoteVideoFrame(uid, width, height, elapsed);
        }
    };

    private void resetAgoraConfig() {
        agoraKit.setChannelProfile(0);
        if (isVideo()) {//视频
            agoraKit.enableVideo();
            agoraKit.muteLocalVideoStream(true);
        } else {//语音
            agoraKit.disableVideo();
            agoraKit.enableAudio();
            agoraKit.muteLocalAudioStream(true);
        }
    }

    private void resetSpeakerMode() {
        if (isVideo()) {//视频
            if (hasHeadset()) {//已插入耳机
                agoraKit.setEnableSpeakerphone(false);
            } else {
                //默认麦克风模式
                agoraKit.setEnableSpeakerphone(true);
            }
        } else {//语音
            //默认听筒模式
            agoraKit.setEnableSpeakerphone(false);
        }
    }

    //检测耳机是否可用
    public boolean hasHeadset() {
        AudioManager audioManager = (AudioManager) App.getInstanse().getSystemService(Context.AUDIO_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            AudioDeviceInfo[] devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
            for (AudioDeviceInfo device : devices) {
                int deviceType = device.getType();
                if (deviceType == AudioDeviceInfo.TYPE_WIRED_HEADSET
                        || deviceType == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
                        || deviceType == AudioDeviceInfo.TYPE_BLUETOOTH_A2DP
                        || deviceType == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
                    return true;
                }
            }
        } else {
            return audioManager.isWiredHeadsetOn() || audioManager.isBluetoothScoOn() || audioManager.isBluetoothA2dpOn();
        }
        return false;
    }

    //切换麦克风模式
    public void enableSpeaker(boolean speaker) {
        agoraKit.setEnableSpeakerphone(speaker);
    }

    public boolean isEnableSpeaker() {
        return agoraKit.isSpeakerphoneEnabled();
    }

    //是否静音
    public void muteLocalAudio() {
        isUserControlLocalVoiceMute = true;
        isLocalVoiceMute = !isLocalVoiceMute;
        if (currentCallState() == CallingState.CallingState_In_Calling) {
            agoraKit.muteLocalAudioStream(isLocalVoiceMute);
        }
        EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_Local_Voice_Mute_Changed, null));
    }

    public boolean isMuteLocalAudio() {
        return isLocalVoiceMute;
    }

    //是否禁止本地视频
    public void muteLocalVideo(boolean mute) {
        agoraKit.muteLocalVideoStream(mute);
    }

    //摄像头切换
    public void toggleCamera() {
        agoraKit.switchCamera();
    }

    //显示本地视频
    public void showLocalVideoToView(View view) {
        VideoCanvas videoCanvas = new VideoCanvas(view);
        videoCanvas.uid = 0;
        videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;
        videoCanvas.view = view;
        agoraKit.setupLocalVideo(videoCanvas);
    }

    //显示本地视频
    public void showRemoteVideoToView(View view) {
        VideoCanvas videoCanvas = new VideoCanvas(view);
        videoCanvas.uid = (int) c2cUserId();
        videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;
        videoCanvas.view = view;
        agoraKit.setupRemoteVideo(videoCanvas);
    }

    //获取通话时间
    public String callDisplayTime() {
        return curCallInfo != null ? curCallInfo.displayCallTime() : "00:00";
    }

    private void doRefreshTask() {
        if (curCallInfo.callState == CallingState.CallingState_In_Calling) {//通话中
            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Refresh_Call_Time, null));
            resetCallInfoToSmallTopView();
        } else {
            if (curCallInfo.callState == CallingState.CallingState_Outgoing_Calling) {//呼叫中-超时检测
                if (curCallInfo.callTime > 0) {
                    long intervel = new Date().getTime() / 1000 - curCallInfo.callTime;
                    if (intervel > 30) {//已超时
                        curCallInfo.callState = CallingState.CallingState_Canceled_2_Timeout;
                        showTips(App.getInstanse().getString(R.string.phone_stats_unresponse));
                        EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                        resetCallInfoToSmallTopView();
                        destroyCall();
                    }
                }
            }
            if (curCallInfo.callState == CallingState.CallingState_Incoming_Waiting) {//来电-超时检测
                if (curCallInfo.callTime > 0) {
                    long intervel = new Date().getTime() / 1000 - curCallInfo.callTime;
                    if (intervel > 30) {//已超时
                        curCallInfo.callState = CallingState.CallingState_Canceled_2_Timeout;
                        showTips(App.getInstanse().getString(R.string.answer_timeout));
                        EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                        resetCallInfoToSmallTopView();
                        destroyCall();
                    }
                }
            }
            if (curCallInfo.incoming_join_time > 0 && curCallInfo.callState == CallingState.CallingState_Incoming_Prepare) {
                long intervel = new Date().getTime() / 1000 - curCallInfo.callTime;
                if (intervel > 3) {//已超时
                    curCallInfo.callState = CallingState.CallingState_Canceled_2_Timeout;
                    showTips(App.getInstanse().getString(R.string.answer_timeout));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                }
            }
        }
    }

    Handler mainHandler = new Handler(Looper.getMainLooper());

    private void startRefreshTimer(long delay) {
        if (timerRefreshTask == null) {
            timerRefreshTask = new Timer();
            timerRefreshTask.schedule(new TimerTask() {
                @Override
                public void run() {
                    //主线程执行
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            doRefreshTask();
                        }
                    });
                }
            }, delay, delay);
        }
    }

    private void stopRefreshTimer() {
        if (timerRefreshTask != null) {
            timerRefreshTask.cancel();
            timerRefreshTask = null;
        }
    }

    private void showTips(String tips) {
        Toast.makeText(App.getInstanse(), tips, Toast.LENGTH_SHORT).show();
    }

    //对外方法
    //新来电
    public void newIncomingCall(RemoteCallInfo remoteCall) {
        if (remoteCall == null || agoraKit == null) {
            return;
        }
        if (remoteCall.isTimeOut) {//通话超时
            //消息显示未接来电
            TelegramManager.getTelegramManager().sendLocalCustomMessage(App.getInstanse(), remoteCall.getRealChatId(), remoteCall.from, remoteCall.done_jsonForMessage(), new TgResultBlock<TgResponse>() {
                @Override
                public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                }

                @Override
                public void onTimeout(Map<String, Object> request) {
                }
            });
            return;
        }
        if (canNewCall()) {
            if (isInCalling()) {//通话中
                //直接取消
                TelegramManager.getTelegramManager().sendLocalCustomMessage(App.getInstanse(), remoteCall.getRealChatId(), remoteCall.from, remoteCall.done_jsonForMessage(), new TgResultBlock<TgResponse>() {
                    @Override
                    public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                    }

                    @Override
                    public void onTimeout(Map<String, Object> request) {
                    }
                });
            } else {
                //语音静音管理
                isLocalVoiceMute = false;
                isUserControlLocalVoiceMute = false;
                //发送接收应答
                TelegramManager.getTelegramManager().callInviteAsk(App.getInstanse(), remoteCall.callId, new TgResultBlock<TgResponse>() {
                    @Override
                    public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                    }

                    @Override
                    public void onTimeout(Map<String, Object> request) {
                    }
                });
                //
                curCallInfo = LocalCallInfo.callWithRemote(remoteCall);
                if (curCallInfo.isMeetingAV) {//视频会议模式

                } else {//1vs1语音视频通话
                    toFullC2CCallView(null, true);
                }
                //开启超时处理机制
                stopRefreshTimer();
                startRefreshTimer(500);
            }
        }
    }

    //对方取消通话
    public void cancelCall(RemoteCallInfo remoteCall) {
        if (curCallInfo == null || remoteCall == null) {
            return;
        }
        if (isInCalling() && curCallInfo.callId == remoteCall.callId) {
            curCallInfo.callState = CallingState.CallingState_C2C_Canceled;
            showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.other_cancle_video_call) : App.getInstanse().getString(R.string.other_cancle_voice_call));
            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
            resetCallInfoToSmallTopView();
            destroyCall();
        }
    }

    //对方离开通话
    public void leaveCall(RemoteCallInfo remoteCall) {
        if (curCallInfo == null || remoteCall == null) {
            return;
        }
        if (isInCalling() && curCallInfo.callId == remoteCall.callId) {
            if (curCallInfo.isMeetingAV) {//会议

            } else {
                if (curCallInfo.callState == CallingState.CallingState_In_Calling) {
                    curCallInfo.callState = CallingState.CallingState_Call_End;
                    showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.other_end_video_call) : App.getInstanse().getString(R.string.other_end_voice_call));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                } else {
                    curCallInfo.callState = CallingState.CallingState_C2C_Canceled;
                    showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.other_cancle_video_call) : App.getInstanse().getString(R.string.other_cancle_voice_call));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                }
            }
        }
    }

    //接听电话
    public void acceptNewCall() {
        if (curCallInfo == null) {
            return;
        }
        if (curCallInfo.callState != CallingState.CallingState_Incoming_Prepare) {
            //准备中
            curCallInfo.callState = CallingState.CallingState_Incoming_Prepare;
            EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
            resetCallInfoToSmallTopView();
            //第一步，生成rtc token
            newCall_step1_createRtcToken();
        }
    }

    //是否可以发起新call
    public boolean canNewCall() {
        return agoraKit != null;
    }

    //是否正在通话
    public boolean isInCalling() {
        if (curCallInfo != null) {
            if (curCallInfo.callState != CallingState.CallingState_None &&
                    curCallInfo.callState != CallingState.CallingState_Outgoing_Prepare_error &&
                    curCallInfo.callState != CallingState.CallingState_Canceled &&
                    curCallInfo.callState != CallingState.CallingState_Canceled_2_Timeout &&
                    curCallInfo.callState != CallingState.CallingState_C2C_Canceled &&
                    curCallInfo.callState != CallingState.CallingState_Call_End) {
                return true;
            }
        }
        return false;
    }

    public static void startC2CNewCall(Activity activity, UserInfo user) {
        new XPopup.Builder(activity)
                .asBottomList(null, new String[]{activity.getString(R.string.video_call_text), activity.getString(R.string.voice_call_text)}, new OnSelectListener() {
                    @Override
                    public void onSelect(int position, String text) {
                        startC2CNewCall(activity, user, position == 0);
                    }
                }).show();
    }

    public static void startC2CNewCall(Activity activity, UserInfo user, boolean isVideo) {
        LocalCallInfo call = new LocalCallInfo();
        call.channelName = UUID.randomUUID().toString();
        call.from = UserInfo.getUserInfo().id;
        call.to = new ArrayList<>(Arrays.asList(user.id));
        call.chatId = user.id;
        call.isVideo = isVideo;
        call.isMeetingAV = false;
        call.callState = CallingState.CallingState_Init;
        call.callTime = new Date().getTime() / 1000;
        CallManager.getCallManager().newCall(call, activity);
    }

    //发起新call
    public void newCall(LocalCallInfo call, Activity fromView) {
        if (canNewCall() && !isInCalling()) {
            //语音静音管理
            isLocalVoiceMute = false;
            isUserControlLocalVoiceMute = false;
            //
            curCallInfo = call;
            //准备中
            curCallInfo.callState = CallingState.CallingState_Outgoing_Prepare;
            if (call.isMeetingAV) {//视频会议模式

            } else {//1vs1语音视频通话
                toFullC2CCallView(fromView, false);
            }
            //第一步，生成rtc token
            newCall_step1_createRtcToken();
        }
    }

    private void newCall_step1_createRtcToken() {
        TelegramManager.getTelegramManager().createRtcToken(App.getInstanse(), curCallInfo.channelName, UserInfo.getUserInfo().id, new TgResultBlock<String>() {
            @Override
            public void onResult(Map<String, Object> request, JsonObject response, String tokenStr) {
                if (curCallInfo.callState == CallingState.CallingState_Outgoing_Prepare) {
                    if (!StringUtils.isEmpty(tokenStr)) {
                        curCallInfo.rtcToken = tokenStr;
                        //下一步
                        newCall_step2_createCallRequest();
                    } else {
                        curCallInfo.callState = CallingState.CallingState_Outgoing_Prepare_error;
                        showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_video_call) : App.getInstanse().getString(R.string.failed_voice_call));
                        EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                        resetCallInfoToSmallTopView();
                        destroyCall();
                    }
                }
                if (curCallInfo.callState == CallingState.CallingState_Incoming_Prepare) {
                    if (!StringUtils.isEmpty(tokenStr)) {
                        curCallInfo.rtcToken = tokenStr;
                        //下一步
                        newCall_step2_joinRoom();
                    } else {
                        curCallInfo.callState = CallingState.CallingState_Canceled;
                        showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_answer_video) : App.getInstanse().getString(R.string.failed_answer_voice));
                        EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                        resetCallInfoToSmallTopView();
                        destroyCall();
                    }
                }
            }

            @Override
            public void onTimeout(Map<String, Object> request) {
                //超时,结束通话
                if (curCallInfo.callState == CallingState.CallingState_Outgoing_Prepare) {
                    curCallInfo.callState = CallingState.CallingState_Outgoing_Prepare_error;
                    showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_video_call) : App.getInstanse().getString(R.string.failed_voice_call));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                }
                if (curCallInfo.callState == CallingState.CallingState_Incoming_Prepare) {
                    curCallInfo.callState = CallingState.CallingState_Canceled;
                    showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_answer_video) : App.getInstanse().getString(R.string.failed_answer_voice));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                }
            }
        });
    }

    private void newCall_step2_createCallRequest() {
        CallBaseInfo baseInfo = new CallBaseInfo();
        baseInfo.channelName = curCallInfo.channelName;
        baseInfo.from = curCallInfo.from;
        baseInfo.to = new ArrayList<>(curCallInfo.to);
        baseInfo.chatId = curCallInfo.chatId;
        baseInfo.isMeetingAV = curCallInfo.isMeetingAV;
        baseInfo.isVideo = curCallInfo.isVideo;
        TelegramManager.getTelegramManager().createCall(App.getInstanse(), baseInfo, new TgResultBlock<TgResponse>() {
            @Override
            public void onResult(Map<String, Object> request, JsonObject response, TgResponse result) {
                if (curCallInfo.callState == CallingState.CallingState_Outgoing_Prepare) {
                    if (result.ok) {
                        curCallInfo.callId = (Long) result.data;
                        //进入声网频道
                        resetAgoraConfig();
                        agoraKit.joinChannel(curCallInfo.rtcToken, curCallInfo.channelName, null, (int) UserInfo.getUserInfo().id);
                        resetSpeakerMode();
                    } else {
                        curCallInfo.callState = CallingState.CallingState_Outgoing_Prepare_error;
                        if (result.errCode == 501) {
                            showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.black_not_call_video) : App.getInstanse().getString(R.string.black_not_call_voice));
                        } else {
                            showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_video_call) : App.getInstanse().getString(R.string.failed_voice_call));
                        }
                        EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                        resetCallInfoToSmallTopView();
                        destroyCall();
                    }
                }
            }

            @Override
            public void onTimeout(Map<String, Object> request) {
                //超时,结束通话
                if (curCallInfo.callState == CallingState.CallingState_Outgoing_Prepare) {
                    curCallInfo.callState = CallingState.CallingState_Outgoing_Prepare_error;
                    showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.failed_video_call) : App.getInstanse().getString(R.string.failed_voice_call));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                }
            }
        });
    }

    private void newCall_step2_joinRoom() {
        //进入声网频道
        resetAgoraConfig();
        agoraKit.joinChannel(curCallInfo.rtcToken, curCallInfo.channelName, null, (int) UserInfo.getUserInfo().id);
        resetSpeakerMode();
    }

    private SensorEventListener sensorEventListener = null;

    @SuppressLint("InvalidWakeLockTag")
    private void initSensor() {
        PowerManager powerManager = (PowerManager) App.getInstanse().getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "Call");
        SensorManager manager = (SensorManager) App.getInstanse().getSystemService(Context.SENSOR_SERVICE);
        if (manager != null) {
            sensorEventListener = new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent sensorEvent) {
                    float value = sensorEvent.values[0];
                    boolean isPickingUp = value < sensorEvent.sensor.getMaximumRange();
                    //打开或者关闭屏幕
                    if (isPickingUp && !wakeLock.isHeld()) {
                        wakeLock.acquire();
                    }
                    if (!isPickingUp && wakeLock.isHeld()) {
                        try {
                            wakeLock.setReferenceCounted(false);
                            wakeLock.release();
                        } catch (Exception e) {

                        }
                    }
                }

                @Override
                public void onAccuracyChanged(Sensor sensor, int accuracy) {

                }
            };
            Sensor proximitysensor = manager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
            manager.registerListener(sensorEventListener, proximitysensor, SensorManager.SENSOR_DELAY_FASTEST);
        }
    }

    private void releaseSensor() {
        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.setReferenceCounted(false);
            wakeLock.release();
            wakeLock = null;
        }
        SensorManager manager = (SensorManager) App.getInstanse().getSystemService(Context.SENSOR_SERVICE);
        if (manager != null && sensorEventListener != null) {
            manager.unregisterListener(sensorEventListener);
            sensorEventListener = null;
        }
    }

    private void destroyCall() {
        //移除近距离传感器通知
        releaseSensor();
        //
        stopRefreshTimer();
        //停止呼叫铃声
        agoraKit.getAudioEffectManager().stopAllEffects();
        LocalNotificationHelper.stopIncoming();
        //离开声网频道
        agoraKit.leaveChannel();
        //移除小窗口
        removeSmallTopView();
        //生成本地消息
        if (!curCallInfo.isSendedLocalMsg) {
            curCallInfo.isSendedLocalMsg = true;
            curCallInfo.endTime = new Date().getTime() / 1000;
            TelegramManager.getTelegramManager().sendLocalCustomMessage(App.getInstanse(), curCallInfo.getRealChatId(), curCallInfo.from, curCallInfo.done_jsonForMessage(), new TgResultBlock<TgResponse>() {
                @Override
                public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                }

                @Override
                public void onTimeout(Map<String, Object> request) {
                }
            });
        }
    }

    //结束call
    public void endCurrentCall() {
        if (curCallInfo != null) {
            if (isInCalling()) {
                if (curCallInfo.callState == CallingState.CallingState_In_Calling) {//通话中
                    curCallInfo.callState = CallingState.CallingState_Call_End;
                    showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.phone_stats_video_finish) : App.getInstanse().getString(R.string.phone_stats_voice_finish));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                    //发出结束通话报文
                    TelegramManager.getTelegramManager().stopCall(App.getInstanse(), curCallInfo.callId, new TgResultBlock<TgResponse>() {
                        @Override
                        public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                        }

                        @Override
                        public void onTimeout(Map<String, Object> request) {
                        }
                    });
                    return;
                } else {
                    curCallInfo.callState = CallingState.CallingState_Canceled;
                    showTips(curCallInfo.isVideo ? App.getInstanse().getString(R.string.phone_stats_video_cancle) : App.getInstanse().getString(R.string.phone_stats_voice_cancle));
                    EventBus.getDefault().post(TgEvent.event(TelegramManager.EUser_TgEvent.EUser_Call_State_Changed, null));
                    resetCallInfoToSmallTopView();
                    destroyCall();
                    //发出取消通话报文
                    if (isIncoming()) {//来电
                        TelegramManager.getTelegramManager().stopCall(App.getInstanse(), curCallInfo.callId, new TgResultBlock<TgResponse>() {
                            @Override
                            public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                            }

                            @Override
                            public void onTimeout(Map<String, Object> request) {
                            }
                        });
                    } else {
                        TelegramManager.getTelegramManager().cancelCall(App.getInstanse(), curCallInfo.callId, new TgResultBlock<TgResponse>() {
                            @Override
                            public void onResult(Map<String, Object> request, JsonObject response, TgResponse obj) {
                            }

                            @Override
                            public void onTimeout(Map<String, Object> request) {
                            }
                        });
                    }
                    return;
                }
            }
        }
        destroyCall();
    }

    //获得当前通话状态
    public CallingState currentCallState() {
        if (curCallInfo != null) {
            return curCallInfo.callState;
        }
        return CallingState.CallingState_None;
    }

    //获得c2c user
    public UserInfo c2cUser() {
        if (curCallInfo != null && !curCallInfo.isMeetingAV) {
            if (!isIncoming()) {
                if (curCallInfo.to != null && curCallInfo.to.size() == 1) {
                    long userId = curCallInfo.to.get(0);
                    return TelegramManager.getTelegramManager().getTgData().contactInfo(userId);
                }
            } else {
                return TelegramManager.getTelegramManager().getTgData().contactInfo(curCallInfo.from);
            }
        }
        return null;
    }

    //获得c2c userid
    public long c2cUserId() {
        if (curCallInfo != null && !curCallInfo.isMeetingAV) {
            if (!isIncoming()) {
                if (curCallInfo.to != null && curCallInfo.to.size() == 1) {
                    return curCallInfo.to.get(0);
                }
            } else {
                return curCallInfo.from;
            }
        }
        return 0;
    }

    //是否视频
    public boolean isVideo() {
        return curCallInfo != null && curCallInfo.isVideo;
    }

    //是否来电
    public boolean isIncoming() {
        return curCallInfo != null && curCallInfo.from != UserInfo.getUserInfo().id;
    }

    private void toFullC2CCallView(Activity from, boolean isNewIncoming) {
        hideSmallTopView();
        if (from != null) {
            C2CCallActivity.start(from, isNewIncoming);
        } else {
            Activity activity = App.getInstanse().appLifecycle.getTopActivity();
            if (activity != null) {
                C2CCallActivity.start(activity, isNewIncoming);
            } else {
                C2CCallActivity.start(App.getInstanse(), isNewIncoming);
            }
        }
    }

    //重置小窗口
    private void resetCallInfoToSmallTopView() {
        IFloatWindow window = FloatWindow.get();
        if (window != null) {
            View rootView = window.getView();
            if (rootView.findViewById(R.id.icon) != null && rootView.findViewById(R.id.text) != null) {
                ImageView icon = rootView.findViewById(R.id.icon);
                TextView text = rootView.findViewById(R.id.text);
                if (isVideo()) {
                    icon.setImageResource(R.drawable.call_video);
                } else {
                    icon.setImageResource(R.drawable.call_audio);
                }
                if (currentCallState() == CallingState.CallingState_In_Calling) {
                    text.setText(callDisplayTime());
                } else if (isInCalling()) {
                    text.setText(App.getInstanse().getString(R.string.waiting_answer));
                } else {
                    switch (currentCallState()) {
                        case CallingState_Canceled:
                            text.setText(App.getInstanse().getString(R.string.cancled_text));
                            break;
                        case CallingState_Canceled_2_Timeout:
                            text.setText(App.getInstanse().getString(R.string.timed_out));
                            break;
                        case CallingState_C2C_Canceled:
                            text.setText(App.getInstanse().getString(R.string.other_cancled_text));
                            break;
                        case CallingState_Call_End:
                            text.setText(App.getInstanse().getString(R.string.call_ended));
                            break;
                        default:
                            text.setText(App.getInstanse().getString(R.string.over_text));
                            break;
                    }
                }
            }
        }
    }

    //显示置顶小窗口
    public void showSmallTopView() {
        IFloatWindow window = FloatWindow.get();
        if (window != null) {
            if (!window.isShowing()) {
                window.show();
            }
        } else {
            View topLayout = LayoutInflater.from(App.getInstanse()).inflate(R.layout.view_av_floating, null);
            topLayout.findViewById(R.id.rootView).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    toFullC2CCallView(null, false);
                }
            });
            int width = (int) App.getInstanse().getResources().getDimension(R.dimen.x160);
            int height = (int) App.getInstanse().getResources().getDimension(R.dimen.x160);
            FloatWindow.with(App.getInstanse())
                    .setView(topLayout)
                    .setWidth(width)
                    .setHeight(height)
                    .setX(ScreenUtils.getScreenWidth() - width)
                    .setY((int) (ScreenUtils.getScreenHeight() * 0.2f))
                    .setDesktopShow(true)
                    .setMoveType(MoveType.slide)
                    .setMoveStyle(500, new AccelerateInterpolator()).
                    setViewStateListener(new ViewStateListener() {
                        @Override
                        public void onPositionUpdate(int i, int i1) {

                        }

                        @Override
                        public void onShow() {
                            Activity activity = App.getInstanse().appLifecycle.getTopActivity();
                            if (activity instanceof C2CCallActivity) {
                                hideSmallTopView();
                            }
                        }

                        @Override
                        public void onHide() {

                        }

                        @Override
                        public void onDismiss() {

                        }

                        @Override
                        public void onMoveAnimStart() {

                        }

                        @Override
                        public void onMoveAnimEnd() {

                        }

                        @Override
                        public void onBackToDesktop() {
                        }
                    }).build();
            FloatWindow.get().show();
        }
        resetCallInfoToSmallTopView();
    }

    //隐藏置顶小窗口
    public void hideSmallTopView() {
        IFloatWindow window = FloatWindow.get();
        if (window != null && window.isShowing()) {
            window.hide();
        }
    }

    //关闭置顶小窗口
    public void removeSmallTopView() {
        IFloatWindow window = FloatWindow.get();
        if (window != null) {
            FloatWindow.destroy();
        }
    }
}
